/**
 * @version: v1.0.2
 * @date:    2018-04-25 18:59:10
 */
/**
 * UI操作层面的通用方法
 * VUE布局、弹窗、ajax操作、页面组件等等
 * 页面中需要设置contextPath，相当于 httpServletRequest.getContextPath()
 * <script>
 *   $UC = {
 *       ctxPath: ""
 *   };
 *   </script>
 */
var $UU = (function (w, d) {
    var $$ = {};

    /**
     * 初始化页面的 vue 组件,返回生成的 vue 对象
     * 例子:
     * var vue = $UU.init({
     *       data:{
     *       },
     *       methods:{
     *          fun1:function(){},
     *          fun2:function(){}
     *       }
     *       created:function(){
     *           console.log("vue created");
     *       }
     * });
     *
     * @param options 参数
     * options.data:
     * options.created:
     * options.mounted:
     * options.methods:
     * options.computed:
     * options.watch:
     *
     * @return {object} vue 对象
     */
    $$.init = function (options) {
        this.loading("show");
        var __this = this;
        options = options || {};

        var settings = {
            data: {
                //element-ui 日期格式控件1
                datePickerOptions1: {
                    disabledDate: function (time) {
                        return time.getTime() < Date.now() - 8.64e7;
                    }
                },
                //element-ui 日期格式控件2
                datePickerOptions2: {
                    shortcuts: [{
                        text: '今天',
                        onClick: function (picker) {
                            picker.$emit('pick', new Date());
                        }
                    }, {
                        text: '昨天',
                        onClick: function (picker) {
                            var date = new Date();
                            date.setTime(date.getTime() - 3600 * 1000 * 24);
                            picker.$emit('pick', date);
                        }
                    }, {
                        text: '一周前',
                        onClick: function (picker) {
                            var date = new Date();
                            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
                            picker.$emit('pick', date);
                        }
                    }]
                },
                //分页
                pagination: {
                    index: 1, //当前页码
                    size: 10, //每页记录数
                    total: 0 //记录总数
                },
                commonTable: {
                    name: '__commonTable',
                    currentRow: null,
                    lockChange: false,
                    lockChangeCount: 0,
                    rowCheckBox: {}
                },
                commonExcel: {
                    pageUrl: "",
                    fields: [],
                    checkedFields: [],
                    currentCheckFields: [],
                    dialogForExcel: false,
                    exportExcelcheckAll: false,
                    excel_btn: false,
                    dialogTitleForExcel: "导出设置",
                    isIndeterminate: false
                }
            },
            methods: {
                commonTableCheckBoxClick: function (val) {
                    var checked = this.commonTable.rowCheckBox[val];
                    if ($UF.isBoolean(checked) && !checked) {
                        if (this.commonTable.lockChange) {
                            this.commonTable.rowCheckBox[val] = true;
                            return;
                        }
                        this.$refs[this.commonTable.name].setCurrentRow(undefined);
                    } else if ($UF.isBoolean(checked) && checked) {
                        if (this.commonTable.lockChange) {
                            this.commonTable.rowCheckBox[val] = false;
                        }
                    }
                },
                commonTableCurrentChange: function (row1, row2) {
                    var __this = this;
                    if (this.commonTable.lockChange && this.commonTable.lockChangeCount > 0) {
                        this.commonTable.lockChangeCount = 0;
                        return;
                    }
                    if (this.commonTable.lockChange) {
                        this.commonTable.lockChangeCount++;
                        this.$refs[this.commonTable.name].setCurrentRow(row2);
                        return;
                    }
                    if (!row1) {
                        $UF.each(this.commonTable.rowCheckBox, function (e) {
                            __this.commonTable.rowCheckBox[e] = false;
                        });
                        this.commonTable.currentRow = null;
                        return;
                    }

                    this.commonTable.rowCheckBox[row1.id] = true;
                    if (row2) {
                        this.commonTable.rowCheckBox[row2.id] = false;
                    }
                    this.commonTable.rowCheckBox = JSON.parse(JSON.stringify(this.commonTable.rowCheckBox));
                    this.commonTable.currentRow = row1;
                }
            },
            computed: {},
            watch: {},
            components: {}
        };
        if ($UF.isFunction(options.data)) {
            settings.data = $UF.extend(settings.data, options.data());
            delete options.data;
        }
        settings = $UF.extend(settings, options);

        //暴露data对象到windows，供调试使用
        window.$data = settings.data;

        //创建Vue对象
        window.$vue = new Vue({
            el: "#app",
            created: function () {
                if ($UF.isFunction(settings.created)) {
                    settings.created.call(this);
                }

            },
            mounted: function () {
                __this.loading("hide");
                if ($UF.isFunction(settings.mounted)) {
                    settings.mounted.call(this);
                }
            },
            data: settings.data,
            methods: settings.methods,
            computed: settings.computed,
            watch: settings.watch,
            components: settings.components
        });
        return window.$vue;
    };

    var _dom = function (str) {
        if (typeof (str) !== 'string') {
            if ((str instanceof Array) || (str[0] && str.length)) {
                return [].slice.call(str);
            } else {
                return [str];
            }
        }
        if (!$$.__create_dom_div__) {
            $$.__create_dom_div__ = document.createElement('div');
        }
        $$.__create_dom_div__.innerHTML = str;
        return [].slice.call($$.__create_dom_div__.childNodes);
    };

    /**
     * 显示或隐藏页面加载动画
     * 例子:
     * $UU.loading("show")
     * $UU.loading("hide")
     *
     * @param action show | hide
     */
    $$.loading = function (action) {
        var loading1 = function (action) {
            var load = '<div class="ui-loading-selector ui-loading fn-hide">\
                <div class="ui-loading-container">\
                <div class="ui-loading-circular_1 ui-loading-circular"></div>\
                <div class="ui-loading-circular_2 ui-loading-circular"></div>\
                <div class="ui-loading-circular_3 ui-loading-circular"></div>\
                <div class="ui-loading-circular_4 ui-loading-circular"></div>\
                <div class="ui-loading-circular_5 ui-loading-circular"></div>\
                <div class="ui-loading-circular_6 ui-loading-circular"></div>\
                <div class="ui-loading-circular_7 ui-loading-circular"></div>\
                <div class="ui-loading-circular_8 ui-loading-circular"></div>\
                <div class="fn-clear"></div>\
            </div></div>';
            var doc = d.querySelector(".ui-loading-selector");
            if (!doc) {
                doc = _dom(load)[0];
                // var first = d.body.lastChild;
                d.body.appendChild(doc);
            }

            // var supportPageOffset = window.pageXOffset !== undefined;
            // var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
            //
            // var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
            // var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;

            // var w = document.documentElement.offsetWidth || document.body.offsetWidth ;
            var h = document.documentElement.clientHeight || document.body.clientHeight;
            doc.style.height = h + "px";
            if (action == "show") {
                doc.classList.remove("fn-hide");
            } else if (action == "hide") {
                doc.classList.add("fn-hide");
            }
        };

        var loading2 = function (action) {
            var load = '<div class="ui-loading-selector el-loading-mask">\
               <div class="el-loading-spinner">\
               <svg viewBox="25 25 50 50" class="circular">\
                   <circle cx="50" cy="50" r="20" fill="none" class="path"></circle>\
               </svg>\
               </div>\
            </div>';

            var doc = d.querySelector(".ui-loading-selector");
            if (!doc) {
                doc = _dom(load)[0];
                d.body.appendChild(doc);
            }

            var dch = document.documentElement.clientHeight || document.body.clientHeight;
            var doh = document.documentElement.offsetHeight || document.body.offsetHeight;
            // console.log(document.documentElement.clientHeight);
            // console.log(document.documentElement.offsetHeight);
            // console.log(document.body.clientHeight);
            // console.log(document.body.offsetHeight);
            // console.log(document.documentElement.scrollHeight);
            // console.log(document.body.scrollHeight);
            // console.log(document.documentElement.scrollTop);
            // console.log(document.body.scrollTop);
            // console.log(window.pageYOffset);
            doc.style.height = (dch > doh ? dch : doh) + "px";

            if (action == "show") {
                doc.classList.remove("fn-hide");
            } else if (action == "hide") {
                doc.classList.add("fn-hide");
            }
        };

        loading2(action);
    };

    return $$;
}(window, document));

/**
 * ajax函数
 *
 */
(function (w, v, $$) {
    var http = {};

    /**
     * ajax get 请求
     * 例子:
     * $UU.http.get(
     *      "http:url", {p1:xxx, p2:xxx},
     *      function(response){
     *          var data = response.data;
     *      },{
     *          loading:        true | false
     *          before:         function(){},
     *          after:          function(){}
     *      }
     * );
     *
     * @param url 请求地址
     * @param data request对象
     * @param success 回调成功对象
     * @param options 其它参数
     *              requestBody {boolean}   body请求
     *              globalError {boolean}   全局处理业务异常
     *              loading     {boolean}   是否显示通用loading动画
     *              before      {function}   请求钱执行的方法
     *              after       {function}   请求后执行的方法
     */
    http.get = function (url, data, success, options) {
        options = options || {};
        if ($UF.isFunction(options.before)) {
            options.before();
        }
        var o = {};
        // o.emulateJSON = !!!options.json;
        var globalError = !!options.globalError;
        o.params = data;
        var loading = !!options.loading;

        if (loading) {
            $$.loading("show");
        }
        v.http.get(url, o).then(function (response) {
            if (globalError && response.data.code && response.data.code != 20000) {
                v.prototype.$message.error('错误信息：' + response.body.msg + '');
            } else {
                success(response);
            }
            
            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        }, function (response) {
            v.prototype.$message.error('发生错误');
            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        });
    };

    /**
     * ajax post 请求
     * 例子:
     * $UU.http.post(
     *      "http:url", {p1:xxx, p2:xxx},
     *      function(response){
     *          var data = response.data;
     *      },{
     *          requestBody:    true | false
     *          loading:        true | false
     *          before:         function(){},
     *          after:          function(){}
     *      }
     * );
     *
     * @param url 请求地址
     * @param data request对象
     * @param success 回调成功对象
     * @param options 其它参数
     *              requestBody {boolean}   body请求
     *              globalError {boolean}   全局处理业务异常
     *              loading     {boolean}   是否显示通用loading动画
     *              before      {function}  请求钱执行的方法
     *              after       {function}  请求后执行的方法
     */
    http.post = function (url, data, success, options) {
        options = options || {};
        if ($UF.isFunction(options.before)) {
            options.before();
        }
        var o = {};
        o.emulateJSON = !!!options.requestBody;
        var globalError = !!options.globalError;
        var loading = !!options.loading;

        if (loading) {
            $$.loading("show");
        }
        // o.params = data;
        v.http.post( url, data, o).then(function (response) {
            if (globalError && response.data.code && response.data.code != 20000) {
                v.prototype.$message.error('错误信息：' + response.body.msg + '');
            } else {
                success(response);
            }
            
            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        }, function (response) {
            v.prototype.$message.error('发生错误');
            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        });
    };


    /**
     * ajax put 请求
     * 例子:
     * $UU.http.put(
     *      "http:url", {p1:xxx, p2:xxx},
     *      function(response){
     *          var data = response.data;
     *      },{
     *          requestBody:    true | false
     *          loading:        true | false
     *          before:         function(){},
     *          after:          function(){}
     *      }
     * );
     *
     * @param url 请求地址
     * @param data request对象
     * @param success 回调成功对象
     * @param options 其它参数
     *              requestBody {boolean}   body请求
     *              globalError {boolean}   全局处理业务异常
     *              loading     {boolean}   是否显示通用loading动画
     *              before      {function}  请求钱执行的方法
     *              after       {function}  请求后执行的方法
     */
    http.put = function (url, data, success, options) {
        options = options || {};
        if ($UF.isFunction(options.before)) {
            options.before();
        }
        var o = {};
        o.emulateHTTP = false;
        o.emulateJSON = !!!options.requestBody;
        var globalError = !!options.globalError;
        var loading = !!options.loading;

        if (loading) {
            $$.loading("show");
        }
        // o.params = data;
        v.http.put($UC.ctxPath + url, data, o).then(function (response) {
            if (globalError && response.data.code && response.data.code != 0) {
                v.prototype.$message.error('错误信息：' + response.body.msg + '');
            } else {
                success(response);
            }

            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        }, function (response) {
            var msg = "发生错误";
            if (response.body) {
                msg = response.data.msg || "";
                if (response.data.data) {
                    msg += "," + (response.data.data.message || "");
                }
            }
            v.prototype.$message.error(msg);
            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        });
    };

    /**
     * ajax delete 请求
     * 例子:
     * $UU.http.delete(
     *      "http:url", {p1:xxx, p2:xxx},
     *      function(response){
     *          var data = response.data;
     *      },{
     *          loading:        true | false
     *          before:         function(){},
     *          after:          function(){}
     *      }
     * );
     *
     * @param url 请求地址
     * @param data request对象
     * @param success 回调成功对象
     * @param options 其它参数
     *              requestBody {boolean}   body请求
     *              globalError {boolean}   全局处理业务异常
     *              loading     {boolean}   是否显示通用loading动画
     *              before      {function}   请求钱执行的方法
     *              after       {function}   请求后执行的方法
     */
    http.delete = function (url, data, success, options) {
        options = options || {};
        if ($UF.isFunction(options.before)) {
            options.before();
        }
        var o = {};
        o.emulateHTTP = false;
        var globalError = !!options.globalError;
        o.params = data;
        var loading = !!options.loading;

        if (loading) {
            $$.loading("show");
        }
        v.http.delete($UC.ctxPath + url, o).then(function (response) {
            if (globalError && response.data.code && response.data.code != 0) {
                v.prototype.$message.error('错误信息：' + response.body.msg + '');
            } else {
                success(response);
            }

            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        }, function (response) {
            var msg = "发生错误";
            if (response.body) {
                msg = response.data.msg || "";
                if (response.data.data) {
                    msg += "," + (response.data.data.message || "");
                }
            }
            v.prototype.$message.error(msg);
            if ($UF.isFunction(options.after)) {
                options.after();
            }
            if (loading) {
                $$.loading("hide");
            }
        });
    };

    $$.http = http;

    //全局拦截器
    v.http.interceptors.push(function (request, next) {
        // console.log("interceptors before");
        // $$.loading("show");
        next(function (response) {
            // $$.loading("hide");
            // console.log("interceptors after");
            if (!response.ok) {
                v.prototype.$message.error("网络异常，错误码:" + response.status + "");
            }
            //自定义逻辑错误
            //TODO
            return response;
        })
    })
})(window, Vue, $UU);

/**
 * Vue表单校验组件,比官方的校验更加灵活，可以脱离<el-form>对象，在任意表单对象中使用
 * 例子：
 *
 */
Vue.use(
    //Vue 自定义表单校验插件
    (function ($) {
        var $$ = {};

        var _current_group = "common";

        var _config = {
            validate_group: {
                common: []
            },

            //验证函数, 返回 true 验证成功，返回 false 验证失败
            validate: function (group) {
                group = group || _current_group;
                // console.log(group);

                var items = this.validate_group[group] || null;
                // console.log(items);

                if (Object.prototype.toString.call(items) != "[object Array]") {
                    return true;
                }

                var v = true;
                for (var i = 0; i < items.length; i++) {
                    if (!_validate_item(items[i])) {
                        v = false;
                    }
                }
                return v;
            }
        };

        var _get_input = function (el) {
            var $el = $(el), $fi = [];
            if ($el.hasClass("el-input")
                || $el.hasClass("el-autocomplete")
                || $el.hasClass("el-select")
            ) {
                $fi = $el.find("input:first");
                $fi.fitype = "input";
            }
            if ($el.hasClass("el-textarea")) {
                $fi = $el.find("textarea:first");
                $fi.fitype = "textarea";
            }
            if ($el.hasClass("el-radio-group")) {
                $fi = $el;
                $fi.fitype = "radio-group";
            }
            if ($el.hasClass("el-input-number")) {
                $fi = $el;
                $fi.fitype = "input-number";
            }
            return $fi;
        };


        var _get_value = function (fi) {
            if (fi.fitype == "radio-group") {
                return fi.find("label.is-active input").val() || "";
            }
            if (fi.fitype == "input-number") {
                return fi.find("input").val() || "";
            }
            return fi.val() || "";
        };

        //单个表单项的验证
        var _validate_item = function (item) {
            // console.log(item);

            var $el = $(item.el), $fi = _get_input(item.el), rules = item.rules;

            var condition = true;
            if ($UF.isFunction(item.condition)) {
                condition = item.condition.call(item.context, item.index);
            } else if ($UF.isBoolean(item.condition)) {
                condition = item.condition;
            }

            $el.parent().removeClass("ui-is-error");
            $el.next().remove();

            if ($fi.length == 0) {
                return true;
            }

            if (!condition) {
                return true;
            }
            // var val = $fi.val().trim() || "";
            // var val = $fi.val() || "";
            var val = _get_value($fi);
            var result = true, err_rule = null;

            if (Object.prototype.toString.call(rules) != "[object Array]") {
                result = _validate_rule(rules, val);
            }

            for (var i = 0; i < rules.length; i++) {
                if (!_validate_rule(rules[i], val)) {
                    result = false;
                    err_rule = rules[i];
                    break;
                }
            }

            //校验失败
            if (!result) {
                if ($fi.fitype != "radio-group"
                    && $fi.fitype != "input-number"
                    && $fi.fitype != "textarea"
                ) {
                    $fi.addClass("el-input__inner");
                }
                if ($fi.fitype == "textarea") {
                    $el.after("<div class='ui-item__error__textarea' style='width:" + $el.css("width") + "; text-align:left;'>" + err_rule.message + "</div>");
                } else {
                    $el.after("<div class='ui-item__error' style='width:" + $el.css("width") + "; text-align:left;'>" + err_rule.message + "</div>");
                }
                $el.parent().addClass("ui-is-error");
            }

            return result;
        };

        //单个规则的验证
        var _validate_rule = function (rule, val) {
            var a = {
                //不能为null和undefined
                not_null: function () {
                    return $UF.validate.notNull(val);
                },
                //验证非空
                required: function () {
                    return $UF.validate.notBlank(val);
                },
                //验证为货币
                money: function () {
                    if ($UF.validate.blank(val)) {
                        return true;
                    }
                    return $UF.validate.money(val.trim());
                },
                //验证为非负数（包括正整数、正小数、和0）
                p_number: function () {
                    if ($UF.validate.blank(val)) {
                        return true;
                    }
                    return $UF.validate.pNumber(val.trim());
                },
                //不能为0
                not_zero: function () {
                    if ($UF.validate.blank(val)) {
                        return true;
                    }
                    return !(0 === Number((val + "").trim()));
                },
                // 长度验证
                length: function () {
                    return $UF.validate.range(val, rule.min || 0, rule.max);
                },
                // 字母，数字验证
                alpha_num: function () {
                    return $UF.validate.alpha_num(val);
                },
                // 数字验证
                number: function (_rule) {
                    return $UF.validate.num_ext(val, _rule.min, _rule.max, _rule.integer, _rule.float, _rule.positive, _rule.negative);
                },
            };

            var result = true;
            for (var key in rule) {
                if (key === "message") {
                    continue;
                }
                if (!(key in a)) {
                    continue;
                }
                result = result && a[key](rule[key]);
            }
            return result;
        };

        var _getGroup = function (rule) {
            return rule.group || "common";
        };

        var _addItem = function (uid, el, rule, context, index) {
            // console.log(el);
            var group_name = _getGroup(rule);
            var rules = rule.rules || [];
            var condition = rule.condition || null;
            var index = index || 0;

            if (!(group_name in _config.validate_group)) {
                _config.validate_group[group_name] = [];
            }
            _config.validate_group[group_name].push({ uid: uid, el: el, context: context, rules: rules, condition: condition, index: index });

            //绑定blur事件
            var $fi = _get_input(el);
            var f = function () {
                _validate_item({ el: el, rules: rules })
            };
            $fi.bind("blur", f);
        };

        var _removeItem = function (uid, rule) {
            var group_name = _getGroup(rule);
            for (var i = 0, flag = true, len = _config.validate_group[group_name].length; i < len; flag ? i++ : i) {
                if (_config.validate_group[group_name][i] && _config.validate_group[group_name][i].uid == uid) {
                    _config.validate_group[group_name].splice(i, 1);
                    flag = false;
                } else {
                    flag = true;
                }
            }
        };

        Vue.prototype.$ui_validate = _config;

        $$.install = function (Vue, options) {
            //自定义表单验证指令,只适用于element-ui表单元素
            Vue.directive('ui-rule', {
                // 当绑定元素插入到 DOM 中。
                inserted: function (el, binding, vnode) {
                    // console.log(el);
                    // console.log(binding);
                    // console.log("inserted: uid -> " + vnode.componentInstance._uid);
                    // var context = vnode.context;
                    // console.log(binding.value);
                    var rule = binding.value;

                    if ($UF.isNumber(rule.index)) {
                        _addItem(vnode.componentInstance._uid, el, rule.rule, vnode.context, rule.index);
                    } else {
                        _addItem(vnode.componentInstance._uid, el, rule, vnode.context);
                    }

                },
                update: function (el, binding, vnode, oldVnode) {
                    // console.log("update");
                },
                componentUpdated: function (el, binding, vnode, oldVnode) {
                    // console.log("componentUpdated");
                },
                unbind: function (el, binding, vnode, oldVnode) {
                    // console.log("unbind: uid -> " + vnode.componentInstance._uid);
                    var rule = binding.value;

                    if ($UF.isNumber(rule.index)) {
                        _removeItem(vnode.componentInstance._uid, rule.rule);
                    } else {
                        _removeItem(vnode.componentInstance._uid, rule);
                    }
                }
            });

            // Vue.directive('ui-rule-index', {
            //     // 当绑定元素插入到 DOM 中。
            //     inserted: function (el, binding, vnode) {
            //         console.log(binding.value);
            //     }
            // });

            // console.log(this);
            // console.log(Vue);

            // Vue.directive('ui-rule-check', {
            //     inserted: function (el, binding, vnode) {
            //         var value = binding.value;
            //         _current_group = value;
            //     },
            //     update: function (el, binding, vnode) {
            //         var oldValue = binding.oldValue;
            //         var value = binding.value;
            //         _current_group = value;
            //         if (oldValue != value) {
            //             //_current_group = value;
            //         }
            //     }
            // });
        };

        return $$;
    })(jQuery)
);